import { MutableRefObject, useCallback } from 'react';
import { AUTH_STORE, LOCAL_HISTORY_SEARCH_RECORD_STORE } from '@/constants';
import { resAddSearch, resDeleteSearch, resSearch } from '@/services/search';
import { isLoginState } from '@/store/authStore';
import { useRequest } from 'ahooks';
import dayjs from 'dayjs';
import {
  atom,
  AtomEffect,
  selector,
  useRecoilState,
  useRecoilValue,
} from 'recoil';
import { isValidTokenTime } from '@/utils/auth';
import { local } from '@/utils/storage';

const subscriptLocalHistoryStore: AtomEffect<LocalHistoryRecord[]> = ({
  onSet,
  setSelf,
  trigger,
}) => {
  onSet((newValue) => {
    local.set(LOCAL_HISTORY_SEARCH_RECORD_STORE, newValue);
  });

  const initSelf = async () => {
    const searchRecords = await resSearch();
    if (searchRecords) {
      setSelf(
        searchRecords.map((value) => {
          return {
            id: value.id,
            keyword: value.keyword,
            time: dayjs(value.created_at).unix(),
          };
        })
      );
    }
  };

  const auth = local.get<AuthStructure>(AUTH_STORE, { token: '', expire: '' });
  if (auth.token && isValidTokenTime(auth.expire)) {
    initSelf();
  } else {
    setSelf(
      local.get<LocalHistoryRecord[]>(
        LOCAL_HISTORY_SEARCH_RECORD_STORE,
        [] as LocalHistoryRecord[]
      )
    );
  }
};

export const localHistorySearchRecordStore = atom<LocalHistoryRecord[]>({
  key: LOCAL_HISTORY_SEARCH_RECORD_STORE,
  default: [],
  effects_UNSTABLE: [subscriptLocalHistoryStore],
});

export const useLocalHistoryRecordStore = () => {
  const [localHistory, setLocalHistory] = useRecoilState(
    localHistorySearchRecordStore
  );
  const isLogin = useRecoilValue(isLoginState);
  const { runAsync: addRun } = useRequest(resAddSearch, { manual: true });
  const { runAsync: deleteRun } = useRequest(resDeleteSearch, { manual: true });

  const deleteRecord = useCallback((keyword: string) => {
    setLocalHistory((preStore) => {
      const index = preStore.findIndex((value) => {
        return value.keyword === keyword;
      });
      preStore[index].id &&
        deleteRun(preStore[index].id!).then(async () => {
          const searchRecords = await resSearch();
          if (searchRecords) {
            setLocalHistory(
              searchRecords.map((value) => {
                return {
                  id: value.id,
                  keyword: value.keyword,
                  time: dayjs(value.created_at).unix(),
                };
              })
            );
          }
        });
      let result = [...preStore];
      result.splice(index, 1);
      return result;
    });
  }, []);

  const addRecord = useCallback(
    async (keyword: string, isUnmount?: MutableRefObject<boolean>) => {
      const param: LocalHistoryRecord = {
        keyword: keyword,
        time: dayjs().unix(),
      };

      if (isLogin) {
        const data = await addRun({ keyword });
        param.id = data.id;
        param.time = dayjs(data.created_at).unix();
      }

      if (!isUnmount?.current) {
        setLocalHistory((preStore) => {
          if (isUnmount?.current) {
            return preStore;
          }
          const index = preStore.findIndex((value) => {
            return value.keyword === keyword;
          });
          let result = [...preStore];
          if (index > -1) {
            result.splice(index, 1);
          }
          result.unshift(param);
          return [...result.slice(0, 5)];
        });
      }
    },
    [isLogin]
  );
  return {
    addRecord,
    deleteRecord,
  };
};
